Don't update the same path source multiple times
authorAlex Crichton <alex@alexcrichton.com>
Wed, 20 May 2015 05:50:26 +0000 (22:50 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 20 May 2015 05:57:37 +0000 (22:57 -0700)
Updating a path source can be a possibly expensive operation (lots of
directories that need to be traversed), and currently the root path source is
updated three times:

* Once when the root package is initially loaded.
* Again when the first resolution pass happens over a graph.
* Finally a third when the second resolution pass happens over the graph.

This commit pushes through the original `Source` trait object into the
`PackageRegistry` and removes the implicit call to `add_sources`, pushing that
call up to the stack a bit.

src/cargo/core/registry.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_fetch.rs
src/cargo/ops/cargo_generate_lockfile.rs
src/cargo/ops/cargo_package.rs
src/cargo/ops/resolve.rs
src/cargo/sources/path.rs

index 3bd5e6a60583f881c1eff3a78c9a569dcff1669c..4bd13c29e7d5ea9bc9b29bdfaa410da55e680c46 100644 (file)
@@ -140,6 +140,11 @@ impl<'cfg> PackageRegistry<'cfg> {
         Ok(())
     }
 
+    pub fn preload(&mut self, id: &SourceId, source: Box<Source + 'cfg>) {
+        self.sources.insert(id, source);
+        self.source_ids.insert(id.clone(), (id.clone(), Kind::Locked));
+    }
+
     pub fn add_sources(&mut self, ids: &[SourceId]) -> CargoResult<()> {
         for id in ids.iter() {
             try!(self.load(id, Kind::Locked));
index 26db527dcd87fc903a92470aec27e3315a175fb3..a927208042b2368fd8579f49fbd9bb1aa3ba0ced 100644 (file)
@@ -98,10 +98,11 @@ pub fn compile<'a>(manifest_path: &Path,
     for key in package.manifest().warnings().iter() {
         try!(options.config.shell().warn(key))
     }
-    compile_pkg(&package, options)
+    compile_pkg(&package, Some(Box::new(source)), options)
 }
 
 pub fn compile_pkg<'a>(package: &Package,
+                       source: Option<Box<Source + 'a>>,
                        options: &CompileOptions<'a>)
                        -> CargoResult<ops::Compilation<'a>> {
     let CompileOptions { config, jobs, target, spec, features,
@@ -127,6 +128,12 @@ pub fn compile_pkg<'a>(package: &Package,
     let (packages, resolve_with_overrides, sources) = {
         let rustc_host = config.rustc_host().to_string();
         let mut registry = PackageRegistry::new(config);
+        if let Some(source) = source {
+            registry.preload(package.package_id().source_id(), source);
+        } else {
+            try!(registry.add_sources(&[package.package_id().source_id()
+                                               .clone()]));
+        }
 
         // First, resolve the package's *listed* dependencies, as well as
         // downloading and updating all remotes and such.
index d4faeffcd189b9b9b0c480c1d27d44283026818d..cbd3382f90da99f780d61dd8ad622dc777aa1e16 100644 (file)
@@ -14,6 +14,7 @@ pub fn fetch(manifest_path: &Path, config: &Config) -> CargoResult<()> {
     let package = try!(source.root_package());
 
     let mut registry = PackageRegistry::new(config);
+    registry.preload(package.package_id().source_id(), Box::new(source));
     let resolve = try!(ops::resolve_pkg(&mut registry, &package));
 
     let ids: Vec<PackageId> = resolve.iter().cloned().collect();
index e120104391958dc0db8d28f8a985187a86f8f2f3..534a7cdc5da14b9a5eb52fa4765e7c82afa248d9 100644 (file)
@@ -24,6 +24,7 @@ pub fn generate_lockfile(manifest_path: &Path, config: &Config)
     try!(source.update());
     let package = try!(source.root_package());
     let mut registry = PackageRegistry::new(config);
+    registry.preload(package.package_id().source_id(), Box::new(source));
     let resolve = try!(ops::resolve_with_previous(&mut registry, &package,
                                                   Method::Everything,
                                                   None, None));
@@ -84,6 +85,7 @@ pub fn update_lockfile(manifest_path: &Path,
         None => to_avoid.extend(previous_resolve.iter()),
     }
 
+    registry.preload(package.package_id().source_id(), Box::new(source));
     let resolve = try!(ops::resolve_with_previous(&mut registry,
                                                   &package,
                                                   Method::Everything,
index 892512d543a224d3da5285397effff73fa61c3f9..ccae355dee9a8a54cf682f10b8078b17fde1ed12 100644 (file)
@@ -178,7 +178,7 @@ fn run_verify(config: &Config, pkg: &Package, tar: &Path)
     let new_pkg = Package::new(new_manifest, &manifest_path, &new_src);
 
     // Now that we've rewritten all our path dependencies, compile it!
-    try!(ops::compile_pkg(&new_pkg, &ops::CompileOptions {
+    try!(ops::compile_pkg(&new_pkg, None, &ops::CompileOptions {
         config: config,
         jobs: None,
         target: None,
index 6ec6a6a15f19ab7805f2ae8f5aede6cf17250451..2d638d5cc515255ccf508772763ec3d0f2b083c6 100644 (file)
@@ -36,8 +36,6 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
                                  previous: Option<&'a Resolve>,
                                  to_avoid: Option<&HashSet<&'a PackageId>>)
                                  -> CargoResult<Resolve> {
-    let root = package.package_id().source_id().clone();
-    try!(registry.add_sources(&[root]));
 
     // Here we place an artificial limitation that all non-registry sources
     // cannot be locked at more than one revision. This means that if a git
index 16681226e1eac84b1da4e266720fb6a5cd0f2022..fe886c2584b9d339a83e99f49a20a370e18a5166 100644 (file)
@@ -59,7 +59,6 @@ impl<'cfg> PathSource<'cfg> {
     }
 
     pub fn read_packages(&self) -> CargoResult<Vec<Package>> {
-
         if self.updated {
             Ok(self.packages.clone())
         } else if self.id.is_path() && self.id.precise().is_some() {